package com.wei.czz.framework.rabbitMQ.listener.blog;

import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.blog.audit.AssignTypeEnum;
import com.wei.czz.common.enums.blog.audit.AuditStatusEnum;
import com.wei.czz.common.enums.rabbitMQ.MqEnum;
import com.wei.czz.common.po.blog.audit.groupUser.BlogAuditGroupUserPo;
import com.wei.czz.common.utils.TimeUtils;
import com.wei.czz.framework.blog.entity.BlogAuditAssignEntity;
import com.wei.czz.framework.blog.entity.BlogAuditEntity;
import com.wei.czz.framework.blog.entity.BlogAuditGroupEntity;
import com.wei.czz.framework.blog.entity.BlogAuditUserConfigEntity;
import com.wei.czz.framework.blog.service.*;
import com.wei.czz.framework.rabbitMQ.message.blog.BlogAuditMessage;
import lombok.AllArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2025-01-19 16:21:07
 * className: BlogAuditQueueListener 博客审核消息监听类
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class BlogAuditQueueListener {

    private static final Logger log = LoggerFactory.getLogger(BlogAuditQueueListener.class);

    private final BlogAuditService blogAuditService;

    private final BlogAuditAssignService blogAuditAssignService;

    private final BlogAuditGroupService blogAuditGroupService;

    private final BlogAuditGroupUserService blogAuditGroupUserService;

    private final BlogAuditUserConfigService blogAuditUserConfigService;

    private final RedissonClient redissonClient;

    /**
     * 博客审核消息监听方法
     * @param blogAuditMessage 消息对象
     */
    @Transactional
    @RabbitListener(queues = { MqEnum.Queue.BLOG_AUDIT })
    public void BlogAuditMessage(BlogAuditMessage blogAuditMessage) {
        log.info("开始处理博客审核消息。{}", blogAuditMessage);

        String lockKey = RedisConstant.LOCK + EntityConstant.BLOG_AUDIT;
        RLock lock = redissonClient.getLock(lockKey);
        // 加锁一分钟
        lock.lock(1, TimeUnit.MINUTES);

        try {

            // 处理消息
            this.handler(blogAuditMessage);

        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }

        log.info("处理博客审核消息完成");
    }

    /**
     * 处理消息
     * @param blogAuditMessage 消息对象
     */
    private void handler(BlogAuditMessage blogAuditMessage) {

        /*
            获取审核记录
         */
        BlogAuditEntity blogAudit = blogAuditService.get(blogAuditMessage.getAuditId());
        if (!AuditStatusEnum.WAIT.getValue().equals(blogAudit.getAuditStatus())) {
            log.warn("博客审核记录不是待审核状态，无法进行自动审核分单");
            return;
        }

        /*
            获取审核分组
         */
        List<BlogAuditGroupEntity> blogAuditGroupList = blogAuditGroupService.findList(
                Collections.singletonList(blogAuditMessage.getAuditType()),
                Collections.singletonList(blogAuditMessage.getAuditLevel())
        );
        if (CollectionUtils.isEmpty(blogAuditGroupList)) {
            log.error("博客审核分组不存在，无法进行自动审核分单");
            return;
        }
        BlogAuditGroupEntity blogAuditGroup = blogAuditGroupList.get(0);

        /*
            获取审核人员
         */
        List<BlogAuditGroupUserPo> blogAuditGroupUserPoList = blogAuditGroupUserService.findEffectList(
                blogAuditGroup.getId()
        );
        if (CollectionUtils.isEmpty(blogAuditGroupUserPoList)) {
            log.error("可用的博客审核分组用户为空，无法进行自动审核分单");
            return;
        }
        Date date = new Date();

        Optional<BlogAuditGroupUserPo> optional = blogAuditGroupUserPoList.stream()
                .peek(blogAuditGroupUserPo -> {
                    Date kpiDate = blogAuditGroupUserPo.getKpiDate();
                    // 计算kpi所在日期距离当前时间是否超过一个月
                    if (this.isMoreThanOneMonth(kpiDate, date)) {
                        // 超过一个月，重置kpi
                        blogAuditGroupUserPo.setKpiDate(TimeUtils.getMonthStartDate(date))
                                .setClaimNum(CommonEnum.ZERO.getValue());
                    }
                })
                .filter(blogAuditGroupUserPo -> {
                    // 校验是否超过最大审核数
                    return blogAuditGroupUserPo.getClaimNum() < blogAuditGroupUserPo.getKpi();
                })
                .min(Comparator.comparingInt(BlogAuditGroupUserPo::getClaimNum).thenComparing(BlogAuditGroupUserPo::getSort));
        if (!optional.isPresent()) {
            log.info("没有可以使用的审核人员，无法进行自动审核分单");
            return;
        }
        BlogAuditGroupUserPo blogAuditGroupUserPo = optional.get();

        /*
            更新审核记录
         */
        BlogAuditEntity updateBlogAudit = new BlogAuditEntity();
        updateBlogAudit.setId(blogAuditMessage.getAuditId())
               .setAuditUserId(blogAuditGroupUserPo.getUserId());
        blogAuditService.saveOrEdit(updateBlogAudit);

        /*
            保存审核分单
         */
        BlogAuditAssignEntity saveBlogAuditAssign = new BlogAuditAssignEntity();
        saveBlogAuditAssign.setBlogId(blogAuditMessage.getBlogId())
                .setAssignType(AssignTypeEnum.AUTO.getValue())
                .setAuditType(blogAuditMessage.getAuditType())
                .setAuditLevel(blogAuditMessage.getAuditLevel())
                .setAuditUserId(blogAuditGroupUserPo.getUserId());
        blogAuditAssignService.saveOrEdit(saveBlogAuditAssign);

        // 更新审核人员信息
        BlogAuditUserConfigEntity updateBlogAuditUserConfig = new BlogAuditUserConfigEntity();
        updateBlogAuditUserConfig.setId(blogAuditGroupUserPo.getConfigId())
                .setKpiDate(blogAuditGroupUserPo.getKpiDate())
                .setClaimNum(blogAuditGroupUserPo.getClaimNum() + 1);
        blogAuditUserConfigService.saveOrEdit(updateBlogAuditUserConfig);

    }

    /**
     * 判断两个日期是否超过一个月
     * @param start 开始日期
     * @param end   结束日期
     * @return true-超过一个月，false-未超过一个月
     */
    public boolean isMoreThanOneMonth(Date start, Date end) {
        // 创建Calendar实例
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();

        // 设置Calendar的时间为给定的Date对象
        cal1.setTime(start);
        cal2.setTime(end);

        // 计算两个日期之间的月份差值
        int diffInMonths = cal2.get(Calendar.MONTH) - cal1.get(Calendar.MONTH);
        int diffInYears = cal2.get(Calendar.YEAR) - cal1.get(Calendar.YEAR);

        // 考虑年份的差异
        diffInMonths += diffInYears * 12;

        // 判断月份差值是否大于等于1
        return diffInMonths >= 1;
    }
}
